package cn.ltgodm.template.user.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.ltgodm.template.common.constant.UserConstants;
import cn.ltgodm.template.common.domain.TreeSelect;
import cn.ltgodm.template.common.domain.entity.Role;
import cn.ltgodm.template.common.domain.entity.User;
import cn.ltgodm.template.common.domain.vo.RoleVO;
import cn.ltgodm.template.common.utils.SecurityUtils;
import cn.ltgodm.template.common.utils.StringUtils;
import cn.ltgodm.template.user.domain.param.MenuParam;
import cn.ltgodm.template.user.domain.param.MenuQueryParam;
import cn.ltgodm.template.common.domain.vo.MenuVO;
import cn.ltgodm.template.user.service.RoleService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.ltgodm.template.common.domain.entity.Menu;
import cn.ltgodm.template.user.service.MenuService;
import cn.ltgodm.template.user.mapper.MenuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wenpeng
 * @description 针对表【lt_menu(菜单权限表)】的数据库操作Service实现
 * @createDate 2024-03-18 20:43:33
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Resource
    private MenuMapper menuMapper;
    @Resource
    private RoleService roleService;

    /**
     * 通过角色id获取权限集合
     *
     * @param roleId 角色id
     * @return 返回权限集合
     */
    @Override
    public Set<String> selectMenuPermsByRoleId(Long roleId) {
        List<String> perms = menuMapper.selectMenuPermsByRoleId(roleId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }

    /**
     * 通过用户id获取权限集合
     *
     * @param userId 用户id
     * @return 返回权限集合
     */
    @Override
    public Collection<String> selectMenuPermsByUserId(Long userId) {
        List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (String perm : perms) {
            if (StringUtils.isNotEmpty(perm)) {
                permsSet.addAll(Arrays.asList(perm.trim().split(",")));
            }
        }
        return permsSet;
    }


    /**
     * 获取菜单列表
     *
     * @param menuQueryParam 菜单查询参数
     * @return 返回菜单列表
     */
    @Override
    public IPage<MenuVO> selectMenuList(MenuQueryParam menuQueryParam) {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<Menu> lqw = getQueryWrapper(menuQueryParam);
        IPage<Menu> page = new Page<>(menuQueryParam.getPageNum(), menuQueryParam.getPageSize());
        if (User.isAdmin(userId)) {
            return menuMapper.selectMenuList(lqw, page);
        } else {
            return menuMapper.selectMenuListByUserId(lqw, userId, page);
        }
    }

    /**
     * 根据菜单编号获取详细信息
     *
     * @param menuId 菜单编号
     * @return 返回菜单信息
     */
    @Override
    public MenuVO selectMenuById(Long menuId) {
        return menuMapper.selectMenuById(menuId);
    }


    /**
     * 获取菜单树形结构列表
     *
     * @param menuQueryParam 菜单查询参数
     * @return 返回菜单树形结构列表
     */
    @Override
    public List<TreeSelect> selectMenuTree(MenuQueryParam menuQueryParam) {
        LambdaQueryWrapper<Menu> lqw = getQueryWrapper(menuQueryParam);
        Page<Menu> page = new Page<>(menuQueryParam.getPageNum(), -1);
        return buildMenuTree(menuMapper.selectMenuList(lqw, page).getRecords());
    }

    /**
     * 加载对应角色菜单列表
     *
     * @param roleId 角色id
     * @return 返回角色拥有菜单id列表
     */
    @Override
    public List<Long> selectMenuListByRoleId(Long roleId) {
        Role role = roleService.getById(roleId);
        return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
    }

    /**
     * 校验菜单名称是否唯一
     *
     * @param menuParam 菜单参数
     * @return 返回是否唯一
     */
    @Override
    public boolean checkMenuNameUnique(MenuParam menuParam) {
        Long menuId = ObjectUtil.isNull(menuParam.getMenuId()) ? -1L : menuParam.getMenuId();
        Menu menu = menuMapper.checkMenuNameUnique(menuParam);
        if (ObjectUtil.isNotNull(menu) && menu.getMenuId().compareTo(menuId) != 0) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增菜单
     *
     * @param menuParam 菜单参数
     * @return 返回新增结果
     */
    @Override
    public int insertMenu(MenuParam menuParam) {
        menuParam.setCreateBy(SecurityUtils.getUsername());
        return menuMapper.insert(menuParam);
    }

    /**
     * 修改菜单
     *
     * @param menuParam 菜单参数
     * @return 返回修改结果
     */
    @Override
    public int updateMenu(MenuParam menuParam) {
        menuParam.setUpdateBy(SecurityUtils.getUsername());
        menuParam.setCreateBy(null);
        return menuMapper.updateById(menuParam);
    }

    /**
     * 判断是否存在子菜单
     *
     * @param menuId 菜单id
     * @return 返回是否存在子菜单
     */
    @Override
    public boolean hasChildByMenuId(Long menuId) {
        int result = menuMapper.hasChildByMenuId(menuId);
        return result > 0;
    }

    /**
     * 判断菜单是否分配给角色
     * @param menuId 菜单id
     * @return 返回是否分配给角色
     */
    @Override
    public boolean checkMenuExistRole(Long menuId) {
        int result = menuMapper.checkMenuExistRole(menuId);
        return result > 0;
    }

    @Override
    public int deleteMenuById(Long menuId) {
        return menuMapper.deleteById(menuId);
    }

    /**
     * 构建菜单树形结构
     *
     * @param menuList 菜单列表
     * @return 返回菜单树形结构
     */
    @Override
    public List<TreeSelect> buildMenuTree(List<MenuVO> menuList) {
        //获取根节点
        List<MenuVO> parentList = menuList.stream().filter(menu -> menu.getParentId().compareTo(0L) == 0).collect(Collectors.toList());
        parentList.stream().filter(menu -> menu.getParentId().compareTo(0L) == 0).forEach(menu -> {
            //获取子节点
            menu.setChildren(getChildren(menu, menuList));
        });
        return parentList.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * 获取子节点
     *
     * @param menu     菜单
     * @param menuList 菜单列表
     * @return 返回子节点
     */
    private List<MenuVO> getChildren(Menu menu, List<MenuVO> menuList) {
        List<MenuVO> children = new ArrayList<>();
        menuList.stream().filter(subMenu -> subMenu.getParentId().compareTo(menu.getMenuId()) == 0).forEach(subMenu -> {
            //获取子节点
            subMenu.setChildren(getChildren(subMenu, menuList));
            children.add(subMenu);
        });
        return children;
    }

    /**
     * 获取查询条件
     *
     * @param menuQueryParam 菜单查询参数
     * @return 返回查询条件
     */
    private LambdaQueryWrapper<Menu> getQueryWrapper(MenuQueryParam menuQueryParam) {
        LambdaQueryWrapper<Menu> lqw = new LambdaQueryWrapper<>();
        lqw
                .eq(StringUtils.isNotBlank(menuQueryParam.getMenuName()), Menu::getMenuName, menuQueryParam.getMenuName())
                .eq(StringUtils.isNotBlank(menuQueryParam.getVisible()), Menu::getVisible, menuQueryParam.getVisible())
                .eq(StringUtils.isNotBlank(menuQueryParam.getStatus()), Menu::getStatus, menuQueryParam.getStatus())
                .in(CollectionUtil.isNotEmpty(menuQueryParam.getMenuTypes()), Menu::getMenuType, menuQueryParam.getMenuTypes())
        ;
        return lqw;
    }

}




